#pragma once
#include<QString>
#include<QIcon>
#include<QUuid>
#include<QFileInfo>
#include<QBuffer>
#include<QDateTime>

#include"../debug.h"
#include"base.qpb.h"
#include"file.qpb.h"
#include"friend.qpb.h"
#include"gateway.qpb.h"
#include"message_storage.qpb.h"
#include"message_transmit.qpb.h"
#include"notify.qpb.h"
#include"speech_recognition.qpb.h"
#include"user.qpb.h"

namespace model{

////////////////////////////////////////////////////////
/// ⼯具函数
////////////////////////////////////////////////////////

// 根据 QByteArray 转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray) {
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

// 获取到图⽚的⼆进制数据
static inline QByteArray loadImageToByteArray(const QString& fileName) {
    // 1. 加载为 QImage
    QImage image(fileName);
    if (image.isNull()) {
        LOG() << "图⽚⽆法加载!";
        return QByteArray();
    }
    // 2. 转换成 QPixmap
    QPixmap pixmap = QPixmap::fromImage(image);
    // 3. 获取图⽚类型, 是 png 还是 jpg 还是啥别的
    QFileInfo fileInfo(fileName);
    QString type = fileInfo.suffix();
    // 4. 进⾏转换
    QByteArray byteArray;
    QBuffer buffer(&byteArray);
    bool ok = false;
    if (type == "png") {
        // 此处的 save ⽀持 BMP, JPG, JPEG, PNG
        ok = pixmap.save(&buffer, "PNG");
    } else if (type == "jpg" || type == "jpeg") {
        ok = pixmap.save(&buffer, "JPG");
    } else if (type == "bmp") {
        ok = pixmap.save(&buffer, "BMP");
    } else {
        LOG() << "图⽚类型不⽀持!";
        return QByteArray();
    }
    if (!ok) {
        // 如果保存失败，返回空的字节数组
        return QByteArray();
    }
    return byteArray;
}

// 获取到⽂件的⼆进制内容
static inline QByteArray loadFileToByteArray(const QString& filename) {
    QFile file(filename);
    bool ok = file.open(QFile::ReadOnly);
    if (!ok) {
        LOG() << "⽂件读取失败!";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

// 把⼆进制数据写⼊⽂件
static inline void writeByteArrayToFile(const QString& filename, const
                                        QByteArray& content) {
    QFile file(filename);
    bool ok = file.open(QFile::WriteOnly);
    if (!ok) {
        LOG() << "⽂件写⼊失败!";
        return;
    }
    file.write(content);
    file.flush();
    file.close();
    return;
}

// 把时间戳转成 01-01 18:00:00 这样的格式化时间
static inline QString formatTime(int64_t timestamp) {
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(static_cast<time_t>(timestamp));
    return dateTime.toString("MM-dd HH:mm:ss");
}

// 获取当前秒级时间戳
static inline int64_t getTime() {
    return QDateTime::currentSecsSinceEpoch();
}

// 构造⼀个 UserInfo
static inline lx::UserInfo makeUserInfo(int index, const QByteArray& avatar) {
    lx::UserInfo userInfo;
    userInfo.setUserId(QString::number(1000 + index));
    userInfo.setNickname("张三" + QString::number(index));
    userInfo.setDescription("这是个性签名" + QString::number(index));
    userInfo.setPhone("18612345678");
    userInfo.setAvatar(avatar);
    return userInfo;
}

static inline lx::UserInfo makeEmptyUserInfo(const QByteArray& avatar) {
    lx::UserInfo userInfo;
    userInfo.setUserId("");
    userInfo.setNickname("");
    userInfo.setDescription("");
    userInfo.setPhone("");
    userInfo.setAvatar(avatar);
    return userInfo;
}

// 构造⼀个⽂本消息对象
static inline lx::MessageInfo makeMessageInfo(int index, const QString& chatSessionId, const QByteArray& avatar) {
    lx::MessageInfo messageInfo;
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(QDateTime::currentMSecsSinceEpoch() / 1000);
    messageInfo.setMessageId(QString::number(3000 + index));
    lx::UserInfo sender = makeUserInfo(index, avatar);
    messageInfo.setSender(sender);
    lx::MessageContent messageContent;
    messageContent.setMessageType(lx::MessageTypeGadget::MessageType::STRING);
    lx::StringMessageInfo stringMessageInfo;
    stringMessageInfo.setContent("这是⼀条消息" + QString::number(index) + ", " + chatSessionId);
    messageContent.setStringMessage(stringMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}


static inline lx::MessageInfo makeEmptyMessageInfo(const QString& chatSessionId, const QByteArray& avatar) {
    lx::MessageInfo messageInfo;
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(QDateTime::currentMSecsSinceEpoch() / 1000);
    messageInfo.setMessageId("");
    lx::UserInfo sender = makeEmptyUserInfo(avatar);
    messageInfo.setSender(sender);
    lx::MessageContent messageContent;
    messageContent.setMessageType(lx::MessageTypeGadget::MessageType::STRING);
    lx::StringMessageInfo stringMessageInfo;
    stringMessageInfo.setContent("");
    messageContent.setStringMessage(stringMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}


////////////////////////////////////////////////////////
/// ⽤⼾信息
////////////////////////////////////////////////////////
class UserInfo {
public:
    QString userId;//用户Id
    QString nickname;//名字
    QString description;//描述
    QString phone; //电话
    QIcon avatar; //头像

    void load(const lx::UserInfo& userInfo) {
        userId = userInfo.userId();
        nickname = userInfo.nickname();
        phone = userInfo.phone();
        description = userInfo.description();
        if (userInfo.avatar().isEmpty()) {
            // 如果服务器上没有拿到头像, 则使⽤默认头像
            avatar = QIcon(":/image/default_avatar.png");
        } else {
            avatar = makeIcon(userInfo.avatar());
        }
    }
};

////////////////////////////////////////////////////////
/// 消息信息
////////////////////////////////////////////////////////

//消息类型
enum MessageType {
    TEXT_TYPE,      // ⽂本消息
    IMAGE_TYPE,     // 图⽚消息
    FILE_TYPE,      // ⽂件消息
    SPEECH_TYPE,    // 语⾳消息
    UNKNOWN_TYPE    // 错误类型
};

class Message {
public:
    QString messageId = "";
    QString chatSessionId = "";
    QString time = "";  //格式化时间

    MessageType messageType = TEXT_TYPE;
    UserInfo sender;
    //实际内容取决于messageType
    QByteArray content;
    //如果是图⽚,⽂件,语⾳类型,表⽰对应的⽂件id
    QString fileId = "";
    //如果是⽂件消息,表⽰⽂件名
    QString fileName = "";

    // ⽣成消息ID
    static QString makeId() {
        return "M" + QUuid::createUuid().toString().sliced(25, 12);
    }

    static Message makeMessage(MessageType messageType, const QString& chatSessionId, const UserInfo& sender,
                           const QByteArray&content, const QString& extraInfo) {
        if (messageType == TEXT_TYPE) {
            return makeTextMessage(chatSessionId, sender, content);
        } else if (messageType == SPEECH_TYPE) {
            return makeSpeechMessage(chatSessionId, sender, content);
        } else if (messageType == IMAGE_TYPE) {
            return makeImageMessage(chatSessionId, sender, content);
        } else if (messageType == FILE_TYPE) {
            return makeFileMessage(chatSessionId, sender, content, extraInfo);
        } else {
            return Message();
        }
    }

    // ⽣成⼀个⽂本消息
    static Message makeTextMessage(const QString& chatSessionId,const UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = TEXT_TYPE;
        message.content = content;
        return message;
    }

    // ⽣成⼀个语⾳消息
    static Message makeSpeechMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = SPEECH_TYPE;
        message.content = content;
        // fileId 在创建空消息时不需要
        // message.fileId = "";
        return message;
    }

    //生成一个图片消息
    static Message makeImageMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = IMAGE_TYPE;
        message.content = content;
        return message;
    }

    //生成一个文件消息
    static Message makeFileMessage(const QString& chatSessionId, const UserInfo& sender, const QByteArray& content, const QString& fileName) {
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = FILE_TYPE;
        message.content = content;
        message.fileName = fileName;
        return message;
    }

    // 从 PB 中加载构造出 Message
    void load(const lx::MessageInfo& messageInfo) {
        messageId = messageInfo.messageId();
        chatSessionId = messageInfo.chatSessionId();
        time = formatTime(messageInfo.timestamp());
        sender.load(messageInfo.sender());
        auto type = messageInfo.message().messageType();
        if (type == lx::MessageTypeGadget::MessageType::STRING) {
            messageType = TEXT_TYPE;
            content = messageInfo.message().stringMessage().content().toUtf8();
        } else if (type == lx::MessageTypeGadget::MessageType::FILE) {
            messageType = FILE_TYPE;
            fileId = messageInfo.message().fileMessage().fileId();
            if (messageInfo.message().fileMessage().hasFileContents()) {
                content = messageInfo.message().fileMessage().fileContents();
            }
            fileName = messageInfo.message().fileMessage().fileName();
        } else if (type == lx::MessageTypeGadget::MessageType::IMAGE) {
            messageType = IMAGE_TYPE;
            fileId = messageInfo.message().imageMessage().fileId();
            if (messageInfo.message().imageMessage().hasImageContent()) {
                content = messageInfo.message().imageMessage().imageContent();
            }
        } else if (type == lx::MessageTypeGadget::MessageType::SPEECH){
            messageType = SPEECH_TYPE;
            fileId = messageInfo.message().speechMessage().fileId();
            if (messageInfo.message().speechMessage().hasFileContents()) {
                content = messageInfo.message().speechMessage().fileContents();
            }
        } else {
            messageType = UNKNOWN_TYPE;
        }
    }
};


////////////////////////////////////////////////////////
/// 聊天会话信息
////////////////////////////////////////////////////////

class ChatSessionInfo {
public:
    QString chatSessionId = "";
    QString chatSessionName = "";
    Message prevMessage;
    QIcon avatar;
    // 当会话为单聊时,表⽰对⽅的⽤⼾id
    // 如果为群聊, 则该字段为""
    QString userId = "";

    void load(const lx::ChatSessionInfo& chatSessionInfo) {
        chatSessionId = chatSessionInfo.chatSessionId();
        chatSessionName = chatSessionInfo.chatSessionName();
        if (chatSessionInfo.hasSingleChatFriendId()) {
            userId = chatSessionInfo.singleChatFriendId();
        }
        // 新的会话没有 prevMessage, 需要先判定再 load
        if (chatSessionInfo.hasPrevMessage()) {
            prevMessage.load(chatSessionInfo.prevMessage());
        }
        if (!chatSessionInfo.hasAvatar() ||
            chatSessionInfo.avatar().isEmpty()) {
            // 响应中没有会话头像
            // 单聊和群聊设置不同的默认头像
            if (userId != "") {
                // 设置单聊头像
                avatar = QIcon(":/image/default_avatar.png");
            } else {
                // 设置群聊头像
                avatar = QIcon(":/image/group_avatar.png");
            }
        } else {
            avatar = makeIcon(chatSessionInfo.avatar());
        }
    }
};

}


